package com.cskaoyan.app.controller;

import com.cskaoyan.app.bean.bo.ChangePassBO;
import com.cskaoyan.app.bean.bo.LoginBO;
import com.cskaoyan.app.bean.common.BaseRespVo;
import com.cskaoyan.app.bean.po.AdminInfoBean;
import com.cskaoyan.app.bean.po.InfoData;
import com.cskaoyan.app.bean.po.LoginUserData;
import com.cskaoyan.app.exception.ValidationException;
import com.cskaoyan.app.service.AdminAuthService;
import com.cskaoyan.app.shiro.CustomAuthToken;
import com.cskaoyan.app.shiro.LoginType;
import com.cskaoyan.app.util.EncryptUtil;
import com.cskaoyan.app.util.ValidationUtil;
import io.swagger.annotations.ApiOperation;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.Date;
import java.util.List;

@RestController
public class AdminAuthController {

    @Autowired
    private AdminAuthService authService;

    @ApiOperation(value = "管理员登录接口", httpMethod = "POST")
    @PostMapping("admin/auth/login")
    public BaseRespVo<Object> login(@RequestBody @Validated LoginBO loginBO, BindingResult bindingResult)
            throws ValidationException {
        ValidationUtil.valid(bindingResult);
        String username = loginBO.getUsername();
        String password = loginBO.getPassword();
        String encrypt = EncryptUtil.encrypt(password);
        Subject subject = SecurityUtils.getSubject();

        // 如果出现异常则说明认证失败
        try {
            subject.login(new CustomAuthToken(username, encrypt, LoginType.ADMIN_PASSWD));
        } catch (AuthenticationException e) {
            return BaseRespVo.unAuthed();
        }

        // 更新访问记录
        Session session = subject.getSession();
        String host = session.getHost();
        Date lastLogin = session.getLastAccessTime();
        authService.updateLogin(username, host, lastLogin);

        LoginUserData loginUserData = new LoginUserData();
        AdminInfoBean adminInfoBean = authService.getInfoBean(username);
        loginUserData.setAdminInfo(adminInfoBean);
        loginUserData.setToken((String) subject.getSession().getId());
        return BaseRespVo.ok(loginUserData);
    }

    @ApiOperation(value = "获取管理员权限列表", httpMethod = "GET")
    @GetMapping("admin/auth/info")
    public BaseRespVo<Object> info(String token)
            throws ValidationException {
        ValidationUtil.checkEmpty(token);
        //整合shiro
        Subject subject = SecurityUtils.getSubject();
        if (!subject.isAuthenticated()) {
            return BaseRespVo.unAuthed();
        }
        //根据primaryPrincipal做查询
        String username = (String) subject.getPrincipals().getPrimaryPrincipal();
        AdminInfoBean infoBean = authService.getInfoBean(username);
        InfoData infoData = new InfoData();
        infoData.setName(infoBean.getNickName());
        infoData.setAvatar(infoBean.getAvatar());

        List<String> roles = authService.getAdminRoles(username);
        infoData.setRoles(roles);
        List<String> perms = authService.getAdminPerm(username);
        infoData.setPerms(perms);
        return BaseRespVo.ok(infoData);
    }

    @ApiOperation(value = "管理员退出", httpMethod = "POST")
    @PostMapping("admin/auth/logout")
    public BaseRespVo<Object> logout() {
        Subject subject = SecurityUtils.getSubject();
        subject.logout();
        return BaseRespVo.ok();
    }

    @ApiOperation(value = "未登录授权重定向地址", httpMethod = "GET")
    @GetMapping("admin/auth/fail")
    public BaseRespVo<Object> unAuthMessage() {
        return BaseRespVo.unAuthed();
    }

    @ApiOperation(value = "管理员修改密码", httpMethod = "POST")
    @PostMapping("admin/profile/password")
    public BaseRespVo<Object> changePass(@RequestBody @Validated ChangePassBO changePassBO,
         BindingResult bindingResult) throws ValidationException {
        ValidationUtil.valid(bindingResult);
        Subject subject = SecurityUtils.getSubject();
        if (!subject.isAuthenticated()) {
            return BaseRespVo.unAuthed();
        }
        String oldPass = changePassBO.getOldPassword();
        String newPass = changePassBO.getNewPassword();
        String confirmPass = changePassBO.getNewPassword2();
        if (!newPass.equals(confirmPass)) {
            throw new ValidationException("两次输入不一致！");
        }

        String username = (String) subject.getPrincipals().getPrimaryPrincipal();
        String adminPass = authService.getAdminPass(username);
        String encrypt = EncryptUtil.encrypt(oldPass);
        if (!encrypt.equals(adminPass)) {
            throw new ValidationException("原密码错误！");
        }
        authService.changePass(username, EncryptUtil.encrypt(newPass));
        return BaseRespVo.ok();
    }
}
